package org.rsbot.event;

import java.util.EventListener;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.rsbot.event.events.RSEvent;

public class EventManager
  implements Runnable
{
  private final Logger log = Logger.getLogger(EventManager.class.getName());

  private final EventMulticaster multicaster = new EventMulticaster();
  private final Map<Integer, EventObject> queue = new HashMap();

  private final Object threadLock = new Object();
  private Thread eventThread;

  public void dispatchEvent(EventObject paramEventObject)
  {
    synchronized (this.queue) {
      int i = 0;
      for (int j = 0; j < this.queue.size(); j++) {
        if (!this.queue.containsKey(Integer.valueOf(j))) {
          this.queue.put(Integer.valueOf(j), paramEventObject);
          i = 1;
          break;
        }
      }
      if (i == 0) {
        this.queue.put(Integer.valueOf(this.queue.size()), paramEventObject);
      }
      this.queue.notifyAll();
    }
  }

  public void processEvent(EventObject paramEventObject)
  {
    this.multicaster.fireEvent(paramEventObject);
  }

  public boolean isEventThread()
  {
    synchronized (this.threadLock) {
      return Thread.currentThread() == this.eventThread;
    }
  }

  public boolean isEventThreadAlive()
  {
    synchronized (this.threadLock) {
      return this.eventThread != null;
    }
  }

  public void killThread(boolean paramBoolean)
  {
    KillEvent localKillEvent = new KillEvent();
    synchronized (localKillEvent) {
      dispatchEvent(localKillEvent);
      if (paramBoolean)
        try {
          localKillEvent.wait();
        } catch (InterruptedException localInterruptedException) {
          this.log.info("wait for kill event interrupted!");
        }
    }
  }

  public void addListener(EventListener paramEventListener)
  {
    this.multicaster.addListener(paramEventListener);
  }

  public void addListener(EventListener paramEventListener, long paramLong)
  {
    this.multicaster.addListener(paramEventListener, paramLong);
  }

  public void removeListener(EventListener paramEventListener)
  {
    this.multicaster.removeListener(paramEventListener);
  }

  public void run()
  {
    if (!isEventThread())
      throw new IllegalThreadStateException();
    while (true)
      try {
        EventObject localEventObject = null;
        synchronized (this.queue) {
          if (!this.queue.isEmpty()) continue;
          try {
            this.queue.wait();
          } catch (Exception localException2) {
            this.log.info("Event Queue: " + localException2.toString());
          }continue;

          int i = 0;
          int j = 0; if (j < this.queue.size() + i) {
            if (!this.queue.containsKey(Integer.valueOf(j))) {
              i++;
            }
            else {
              localEventObject = (EventObject)this.queue.remove(Integer.valueOf(j));
              continue;
            }
            j++; continue;
          }

        }

        if ((localEventObject instanceof KillEvent)) {
          this.eventThread = null;
          synchronized (localEventObject) {
            localEventObject.notifyAll();
          }
          return;
        }
        try {
          processEvent(localEventObject);
        } catch (java.lang.ThreadDeath ) {
          this.eventThread = null;
          localEventObject.notifyAll();
          return;
        } catch (Throwable ) {
          ???.printStackTrace();
        }
        synchronized (localEventObject) {
          localEventObject.notifyAll();
        }

        continue;
      }
      catch (Exception localException1)
      {
        this.log.info("Event Queue: " + localException1.toString());
        localException1.printStackTrace();
      }
  }

  public void start()
  {
    synchronized (this.threadLock) {
      if (this.eventThread != null) {
        throw new IllegalThreadStateException();
      }
      this.eventThread = new Thread(this, "EventQueue-" + hashCode());
      this.eventThread.setDaemon(true);
      this.eventThread.start();
    }
  }

  public static class KillEvent extends RSEvent
  {
    private static final long serialVersionUID = 3426050317048250049L;

    public void dispatch(EventListener paramEventListener)
    {
    }

    public long getMask()
    {
      return -1L;
    }
  }
}